package com.jule.robot.valve.gate;

import com.jule.db.entities.*;
import com.jule.db.proxy.EntityProxy;
import com.jule.robot.model.BlindActionRateModel;
import com.jule.robot.model.CardValueModel;
import com.jule.robot.model.HandCardTypeModel;
import com.jule.robot.model.eenum.PlayTypeEnum;
import com.jule.robot.util.StringTools;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

public class RobotConfigHandler {
    private final static Logger logger = LoggerFactory.getLogger(RobotConfigHandler.class);
    private static RobotCommonConfigModel robotCommonConfig = null;
    private static ConcurrentMap<String, RobotConfigForPlaytypeModel> robotConfigForPlaytype = new ConcurrentHashMap<>();
    private static ConcurrentMap<String, String> cardLevelForPlaytype = new ConcurrentHashMap<>();
    private static ConcurrentMap<String, RobotHandCardConfigModel> handCardConfigMap = new ConcurrentHashMap<>();

    //期望值（期望牌型）：用于判断手牌是否直接弃牌，小于此牌型的牌，在第一轮次直接弃牌
    private final static Map<Integer, HandCardTypeModel> CARDTYPE_EXPECTED_VALUE = new HashMap<Integer, HandCardTypeModel>(){{
        put(2, new HandCardTypeModel(new CardValueModel('♠', 'K'), new CardValueModel('♥', 'T'), new CardValueModel('♦', '5')));
        put(3, new HandCardTypeModel(new CardValueModel('♠', 'A'), new CardValueModel('♥', 'J'), new CardValueModel('♦', '6')));
        put(4, new HandCardTypeModel(new CardValueModel('♠', '5'), new CardValueModel('♥', '5'), new CardValueModel('♦', 'T')));
        put(5, new HandCardTypeModel(new CardValueModel('♠', '9'), new CardValueModel('♥', '9'), new CardValueModel('♦', 'T')));
    }};

    //执行概率配置的牌型：用于判断手牌是否根据概率配置表的数据，来执行弃牌、加注、跟注等操作
    private final static Map<Integer, HandCardTypeModel> CARDTYPE_MORE_THAN_TO_EXEC_RATE = new HashMap<Integer, HandCardTypeModel>(){{
        put(2, new HandCardTypeModel(new CardValueModel('♠', '3'), new CardValueModel('♥', '4'), new CardValueModel('♦', '5')));
        put(3, new HandCardTypeModel(new CardValueModel('♠', '3'), new CardValueModel('♥', '4'), new CardValueModel('♦', '5')));
        put(4, new HandCardTypeModel(new CardValueModel('♠', '3'), new CardValueModel('♥', '4'), new CardValueModel('♦', '5')));
        put(5, new HandCardTypeModel(new CardValueModel('♠', '3'), new CardValueModel('♥', '4'), new CardValueModel('♦', '5')));
    }};

    private final static Map<Integer, BlindActionRateModel> BLIND_ACTION_RATE = new HashMap<Integer, BlindActionRateModel>(){{
        put(1, new BlindActionRateModel(20, 100, 0));
        put(2, new BlindActionRateModel(15, 90, 10));
        put(3, new BlindActionRateModel(25, 50, 50));
        put(4, new BlindActionRateModel(15, 40, 60));
        put(5, new BlindActionRateModel(15, 20, 80));
        put(6, new BlindActionRateModel(15, 10, 90));
        put(7, new BlindActionRateModel(15, 5, 95));
        put(8, new BlindActionRateModel(15, 2, 98));
        put(9, new BlindActionRateModel(10, 2, 98));
        put(10, new BlindActionRateModel(10, 2, 98));
        put(11, new BlindActionRateModel(10, 2, 98));
        put(12, new BlindActionRateModel(10, 2, 98));
        put(13, new BlindActionRateModel(10, 2, 98));
        put(14, new BlindActionRateModel(10, 2, 98));
        put(15, new BlindActionRateModel(10, 2, 98));
        put(16, new BlindActionRateModel(10, 2, 98));
        put(17, new BlindActionRateModel(10, 2, 98));
        put(18, new BlindActionRateModel(10, 2, 98));
        put(19, new BlindActionRateModel(10, 2, 98));
        put(20, new BlindActionRateModel(10, 2, 98));
    }};

    public static RobotCommonConfigModel getRobotCommonConfig(){
        if(null == robotCommonConfig){
            robotCommonConfig = EntityProxy.OBJ.getSingleResult("1=1",null, RobotCommonConfigModel.class);
        }

        if(null == robotCommonConfig){
            logger.error("找不到 公用 配置：RobotCommonConfigModel");
        }
        return robotCommonConfig;
    }

    public static RobotConfigForPlaytypeModel getRobotConfigForPlaytype(String playType, String cardLevel){
        RobotConfigForPlaytypeModel model = null;
        String cacheKey = playType+"|"+cardLevel;
        if(robotConfigForPlaytype.containsKey(cacheKey)){
            return robotConfigForPlaytype.get(cacheKey);
        }else{
            Map<String,Object> paramsMap = new HashMap<>();
            paramsMap.put("play_type", playType);
            paramsMap.put("card_level", cardLevel);

            model = EntityProxy.OBJ.getSingleResult("obj.playType = :play_type and obj.cardLevel = :card_level", paramsMap, RobotConfigForPlaytypeModel.class);
            if(null != model){
                robotConfigForPlaytype.put(cacheKey, model);
            }
        }

        if(null == model){
            logger.error("找不到 玩法 对应配置：RobotConfigForPlaytypeModel， playType->{}, cardLevel->{}", playType, cardLevel);
            model = getRobotConfigForPlaytype("91001001", cardLevel);
        }
        return model;
    }

//    public static String getCardLevel(String playType, int cardType){
//        String cardLevel = "";
//        String cacheKey = playType+"|"+cardType;
//        if(cardLevelForPlaytype.containsKey(cacheKey)){
//            cardLevel = cardLevelForPlaytype.get(cacheKey);
//        }else{
//            Map<String,Object> paramsMap = new HashMap<>();
//            paramsMap.put("play_type", playType);
//            paramsMap.put("card_type", cardType);
//
//            RobotCardLevelConfigModel model = EntityProxy.OBJ.getSingleResult("obj.playType = :play_type and obj.cardType = :card_type", paramsMap, RobotCardLevelConfigModel.class);
//            if(null != model){
//                cardLevelForPlaytype.put(cacheKey, model.getCardLevel());
//                cardLevel = model.getCardLevel();
//            }
//        }
//
//        logger.debug("查询牌力值结果， playType->{}, cardType->{}， cardLevel->{}", playType, cardType, cardLevel);
//
//        if(StringUtils.isBlank(cardLevel)){
//            logger.error("找不到 牌力值 对应配置：RobotCardLevelConfigModel， playType->{}, cardType->{}， 将牌力值默认为‘E’。", playType, cardType);
//            cardLevel = "E";
//        }
//
//        return cardLevel;
//    }

    public static void setRobotCommonConfig(RobotCommonConfigModel robotCommonConfig) {
        RobotConfigHandler.robotCommonConfig = robotCommonConfig;
    }

    public static void setRobotConfigForPlaytype(RobotConfigForPlaytypeModel configForPlaytype){
        String cacheKey = configForPlaytype.getPlayType()+"|"+configForPlaytype.getCardLevel();
        robotConfigForPlaytype.put(cacheKey, configForPlaytype);
    }

    public static void setCardLevelForPlaytype(RobotCardLevelConfigModel model){
        String cacheKey = model.getPlayType()+"|"+model.getCardType();
        cardLevelForPlaytype.put(cacheKey, model.getCardLevel());
    }

    public static void setHandCardConfig(RobotHandCardConfigModel model){
        String cacheKey = (model.getPlayType()+"|"+model.getCardType()+"|"+StringTools.sortForPoker(model.getContainsCards())).toUpperCase();
        handCardConfigMap.put(cacheKey, model);
    }

    public static RobotHandCardRateConfigModel getHandCardRateConfigModel(int gameId, HandCardTypeModel cardTypeModel, int humanCount){
        RobotHandCardRateConfigModel rateModel = new RobotHandCardRateConfigModel();
        if(null == cardTypeModel){
            logger.error("获取机器人行为概率 ERROR, cardTypeModel is NULL. gameId->{}", gameId);
            return rateModel;
        }

        String playType = "other"; //玩法暂时只区分 Joker 和其它玩法
        if(gameId == PlayTypeEnum.Joker.getValue()){
            playType = "joker";
        }
        String cardType = cardTypeModel.getTypeName().replaceAll("Joker", "");
        String cardValue = StringTools.sortForPoker(cardTypeModel.getCardValueString());

        if(cardType.equals(HandCardTypeModel.TYPE_PAIR)){
            String dupilicateChar = StringTools.getDuplicateChar(cardValue);
            cardValue = dupilicateChar + dupilicateChar;
        }else if(cardType.equals(HandCardTypeModel.TYPE_HIGH_CARD)){
            cardValue = cardValue.charAt(0)+"";
        }else if(cardType.equals(HandCardTypeModel.TYPE_FLUSH) && gameId == PlayTypeEnum.Joker.getValue()){
            cardValue = new StringBuilder().append(cardValue.charAt(0)).append(cardValue.charAt(1)).toString();
        }else if(cardType.equals(HandCardTypeModel.TYPE_FLUSH) && playType.equals("other")){
            cardValue = new StringBuilder().append(cardValue.charAt(0)).toString();
        }

        String cacheKey = (playType+"|"+cardType+"|"+cardValue).toUpperCase();
        logger.debug("获取机器人手牌数据，cacheKey->{}", cacheKey);
        if(handCardConfigMap.containsKey(cacheKey)){
            RobotHandCardConfigModel configModel = handCardConfigMap.get(cacheKey);
            if(configModel.getRateMap().containsKey(humanCount)){
                rateModel = configModel.getRateMap().get(humanCount);
            }else{
                logger.error("获取机器人行为概率失败，找不到对应人数的概率配置, gameId->{}, playType->{}, cardType->{}, cardValue->{}, humanCount->{}", gameId, playType, cardType, cardValue, humanCount);
            }
        }else{
            logger.error("获取机器人行为概率失败，找不到手牌基础配置, gameId->{}, playType->{}, cardType->{}, cardValue->{}, cacheKey->{}", gameId, playType, cardType, cardValue, cacheKey);
        }

        return rateModel;
    }

    /**
     * 获得期望值（期望牌型）：用于判断手牌是否直接弃牌，小于此牌型的牌，在第一轮次直接弃牌牌型
     * @param onSeatPlayerCnt
     * @return
     */
    public static HandCardTypeModel getCardForExpect(int onSeatPlayerCnt){
        HandCardTypeModel cardType = null;
        if(CARDTYPE_EXPECTED_VALUE.containsKey(onSeatPlayerCnt)){
            cardType = CARDTYPE_EXPECTED_VALUE.get(onSeatPlayerCnt);
        }
        return cardType;
    }

    /**
     * 获得执行概率配置的牌型：用于判断手牌是否根据概率配置表的数据，来执行弃牌、加注、跟注等操作。大于等于此牌型的，执行概率配置。
     * @param onSeatPlayerCnt
     * @return
     */
    public static HandCardTypeModel getCardForExecConfigRate(int onSeatPlayerCnt){
        HandCardTypeModel cardType = null;
        if(CARDTYPE_MORE_THAN_TO_EXEC_RATE.containsKey(onSeatPlayerCnt)){
            cardType = CARDTYPE_MORE_THAN_TO_EXEC_RATE.get(onSeatPlayerCnt);
        }
        return cardType;
    }

    /**
     * 获得盲牌时的行动概率
     * @param betRoundId
     * @return
     */
    public static BlindActionRateModel getBlindActionRate(int betRoundId){
        BlindActionRateModel actionRate = new BlindActionRateModel(20, 100, 0);
        if(BLIND_ACTION_RATE.containsKey(betRoundId)){
            actionRate = BLIND_ACTION_RATE.get(betRoundId);
        }
        return actionRate;
    }
}
